﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using iLangl.Transport;
using log4net;
using iLangl.Transport.Communication;
using System.ServiceModel;
using System.ServiceModel.Description;
using iLangl.LanguageWire;
using iLangl.Plugin;
using iLangl.Plugin.ConfigFileSettings;
using iLangl.LanguageWire.Managers;

namespace iLangl.LanguageWireAPI.Services
{
	partial class LanguageWireAPI : ServiceBase
	{
		private static ILog log = LogManager.GetLogger(typeof(LanguageWireAPI));
		protected ServiceHost transporthost = null;
		Uri baseAddress;

		protected ITransport transport = new WCFConsumer("http://localhost:8080/ilangl/transport");

		IRobot sentrobot;
		IRobot getrobot;

		public LanguageWireAPI()
		{
			log4net.Config.XmlConfigurator.Configure();

			ConfigurationFactory.Instance.Initialize(new FileConfigurationFactory());

			// Initializae Transport Host
			ServiceMetadataBehavior smb;
			baseAddress = new Uri("http://localhost/languagewireAPI");
			transporthost = new ServiceHost(typeof(WCFTransport), baseAddress);
			smb = new ServiceMetadataBehavior();

			smb.HttpGetEnabled = true;
			smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
			transporthost.Description.Behaviors.Add(smb);

			EnableDebug(transporthost);

			transporthost.AddServiceEndpoint(typeof(ITransport), new BasicHttpBinding(), baseAddress);
			//Initialize Business Model
			Facade.Instance.Initialize(new TPFacade());

			//Ilangl Business Model Test Setup
			//TODO: Implement Consumer Transport for LanguageWire
			Facade.Instance.StateMachine.SetMutlyThreading(false);

			InitializeComponent();

			//Initialize Sent Robot
			sentrobot = new PackagesRobot();
			IRobotGet robotGet = new PackagesRobotGet(sentrobot, TransportConfiguration.Instance.OutcomePackageFolder);
			IRobotSet robotSet = new PackagesRobotSent(sentrobot, transport);

			sentrobot.GetOperation = robotGet;
			sentrobot.SetOperation = robotSet;

			//Initialize Get Robot
			getrobot = new PackagesRobot();
			robotGet = new PackagesRobotGet(getrobot, TransportConfiguration.Instance.IncomePackageFolder);
			robotSet = new PackagesRobotExecute(getrobot);

			getrobot.GetOperation = robotGet;
			getrobot.SetOperation = robotSet;
		}

		private void EnableDebug(ServiceHost sh)
		{
			ServiceDebugBehavior debug = sh.Description.Behaviors.Find<ServiceDebugBehavior>();
			if (debug == null)
			{
				sh.Description.Behaviors.Add(
					new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });
			}
			else
			{
				// make sure setting is turned ON     
				if (!debug.IncludeExceptionDetailInFaults) { debug.IncludeExceptionDetailInFaults = true; }
			}
		}

		private bool IsStart = false;
		protected override void OnStart(string[] args)
		{
			IsStart = true;
			timer1.Start();
			timerSent.Start();
			timerGet.Start();

			transporthost.Open();
			log.DebugFormat("iLangl LangugeWire Service Started");
		}

		protected override void OnStop()
		{
			IsStart = false;
			timer1.Start();
			timerSent.Stop();
			timerGet.Stop();

			transporthost.Close();
			log.DebugFormat("iLangl LangugeWire Service Stopped");
		}

		private void timerSent_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
		{
			sentrobot.Execute();
		}

		private void timerGet_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
		{
			getrobot.Execute();
		}

		static bool IsRun = false;
		/// <summary>
		/// Timer event for Synchronization
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
		{

			if (IsRun)
				return;

			IsRun = true;
			try
			{
				log.Info("Timer Tick");

				SynchronizationManager.Instance.Synchronize();

			}
			catch (System.Exception ex)
			{
				log.Error(ex);
			}
			finally
			{
				IsRun = false;
			}
		}


	}
}
